from django.shortcuts import render
import ast
# Create your views here.
from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore
import json
from django.http import JsonResponse
from .filters import *
from django import forms
from django.core.paginator import Paginator
from django.shortcuts import redirect
import datetime
from django.utils import timezone
from public.models import SystemsLists, HostsLists, AnsibleTasks
from public.viewFunc.ansibleIndex import AnsibleOpt
from django.db import close_old_connections
import redis
from onecup.settings import REDIS_ADDR, REDIS_PORT, REDIS_PD, result_db, ansible_result_redis_db, DES_SECRET_KEY
from .promQL import promQL
from public.viewFunc.util import des_decrypt
from tzlocal import get_localzone

scheduler = BackgroundScheduler()
scheduler.add_jobstore(DjangoJobStore(), 'default')


class JobTypeList:
    @staticmethod
    def test(user):
        print("hello apscheduler %s!!!" % user.username)

    @staticmethod
    def fetchpromresult(user, interval):
        allowinterval = ('1d', '1h')
        if interval not in allowinterval:
            interval = '1d'
        fetchpr = promQL()
        fetchpr.getnodeinfo(interval)

    @staticmethod
    def updatetaskresult(user):
        tasklist = AnsibleTasks.objects.filter(AnsibleResult='')
        if tasklist:
            r = redis.Redis(host=REDIS_ADDR, password=REDIS_PD, port=REDIS_PORT, db=ansible_result_redis_db)
            a = redis.Redis(host=REDIS_ADDR, password=REDIS_PD, port=REDIS_PORT, db=result_db)
            for task in tasklist:
                rlist = r.lrange(task.AnsibleID, 0, -1)
                rlen = 0
                max_len = 1024*1024*8
                for i in range(len(rlist)):
                    rlen += len(rlist[i])
                    if rlen > max_len:
                        rlist = rlist[:i]
                        print("over the max len")
                        break
                try:
                    tmpar = json.dumps([json.loads(i.decode()) for i in rlist])
                    task.AnsibleResult = tmpar
                    ct = a.get('celery-task-meta-%s' % task.CeleryID).decode()
                    task.CeleryResult = ct
                    task.save()
                except:
                    pass

    @staticmethod
    def updatejobstatus(user):
        joblist = SchedulerJob.objects.filter(Jobstatus__lt=2)
        for i in joblist:
            sjob = scheduler.get_job(i.id)
            if not sjob:
                i.Jobstatus = 2
                i.save()

    @staticmethod
    def execplaybook(user, systemname, playbook, become_user=None, become_pass=None, extra_vars=None):
        remote_addr = '127.0.0.1'
        close_old_connections()
        system = SystemsLists.objects.get(systemname=systemname)
        remote_user = system.ssh_user
        remote_pass = str(des_decrypt(DES_SECRET_KEY, system.ssh_pass), 'utf-8')
        become = {}
        if become_user:
            become['user'] = become_user
            become['pass'] = become_pass
        data = []
        hostlst = HostsLists.objects.filter(systemname=systemname, manage=True)
        for host in hostlst:
            data.append({
                'ip': host.ip,
                'groups': host.groups,
                'username': remote_user,
                'password': remote_pass,
                'become': become,
            })
        s = AnsibleOpt.ansible_playbook(
            systemname=systemname,
            playbook=playbook,
            inventory=data,
            user=user,
            extra_vars=extra_vars,
            **{'label': remote_addr}
        )
        print("execplaybook systemname:%s" % systemname)


class SchedulerJobForm(forms.Form):
    jobname = forms.CharField(required=True, label='任务名称', error_messages={"required": "任务名称不能为空"})
    jobtype = forms.CharField(required=True, label='任务类型', error_messages={'required': u'任务类型不能为空'})


def SchedulerJobList(request):
    """ansible任务列表页"""
    sjob = SchedulerJobFilter(request.GET, queryset=SchedulerJob.objects.all())
    paginator = Paginator(sjob.qs, 10)
    page = request.GET.get('page')
    page_obj = paginator.get_page(page)
    total = paginator.num_pages
    context = {'page_obj': page_obj, 'total': total, 'paginator': paginator,
               'is_paginated': True, 'filter': sjob, }
    return render(request, 'myscheduler/schedulerjob_list.html', context)


def SchedulerTypeList(request):
    """ansible任务列表页"""
    stype = SchedulerTypeFilter(request.GET, queryset=SchedulerTpye.objects.all())
    paginator = Paginator(stype.qs, 10)
    page = request.GET.get('page')
    page_obj = paginator.get_page(page)
    total = paginator.num_pages
    context = {'page_obj': page_obj, 'total': total, 'paginator': paginator,
               'is_paginated': True, 'filter': stype, }
    return render(request, 'myscheduler/schedulertype_list.html', context)


def SchedulerJObResult(request):
    """ansible任务列表页"""
    sjobresult = SJobResultFilter(request.GET, queryset=DjangoJobExecution.objects.all())
    paginator = Paginator(sjobresult.qs, 10)
    page = request.GET.get('page')
    page_obj = paginator.get_page(page)
    total = paginator.num_pages
    context = {'page_obj': page_obj, 'total': total, 'paginator': paginator,
               'is_paginated': True, 'filter': sjobresult, }
    return render(request, 'myscheduler/sjobresult_list.html', context)


def SchedulerJobAdd(request):
    obj = SchedulerJobForm()
    user = request.user
    shdtype = SchedulerTpye.objects.all()
    schedulertype = shdtype.values_list('Name', flat=True)
    if request.method == 'POST':
        sJob_form = SchedulerJobForm(request.POST)
        if sJob_form.is_valid():
            jobname = request.POST.get('jobname')
            jobtype = request.POST.get('jobtype')
            jobargs = request.POST.get('jobargs')
            reservation = request.POST.get('reservation')
            resttime = reservation.split('-')
            # current_tz = timezone.get_current_timezone()
            current_tz = get_localzone()
            starttime = datetime.datetime.strptime(resttime[0].strip(), '%m/%d/%Y')
            starttime = current_tz.localize(starttime)
            endtime = datetime.datetime.strptime(resttime[1].strip(), '%m/%d/%Y')
            endtime = current_tz.localize(endtime)
            plan = request.POST.get('plan')
            plantime = request.POST.get('plantime')
            if plantime:
                plantime = datetime.datetime.strptime(plantime, '%m/%d/%Y %I:%M %p')
                plantime = current_tz.localize(plantime)
            else:
                plantime = None
            intervals = request.POST.get('intervals')
            if intervals:
                intervals = int(intervals)
            else:
                intervals = 0
            crontime = request.POST.get('crontime')
            remark = request.POST.get('remark')
            jtype = SchedulerTpye.objects.get(Name=jobtype)
            if not jtype:
                msg = "任务模板不存在，请排查问题！"
                return render(request, 'public/fail.html', {'msg': msg})
            sJOb_indb = SchedulerJob.objects.filter(JobName=jobname)
            if sJOb_indb:
                msg = "任务已存在，请点击返回重新填写"
                return render(request, 'public/fail.html', {'msg': msg})
            else:
                trigger = ['date', 'interval', 'cron']
                jobtrigger = trigger[(int(plan)-1)]
                jargslist = GetJobarg(jtype, jobargs, user)
                if not jargslist:
                    msg = "任务参数填写错误，请点击返回重新填写"
                    return render(request, 'public/fail.html', {'msg': msg})
                try:
                    newjob = SchedulerJob.objects.create(
                        JobName=jobname,
                        Jobtpye=jtype,
                        Jobargs=jobargs,
                        reservation=reservation,
                        starttime=starttime,
                        endtime=endtime,
                        Jobowner=user,
                        plan=int(plan),
                        intervals=intervals,
                        crontime=crontime,
                        plantime=plantime,
                        Remark=remark
                    )
                    if int(plan) == 1:
                        scheduler.add_job(getattr(JobTypeList, jtype.Shlrmethod), jobtrigger, args=jargslist, id=str(newjob.id), run_date=plantime)
                    elif int(plan) == 2:
                        scheduler.add_job(getattr(JobTypeList, jtype.Shlrmethod), jobtrigger, args=jargslist, id=str(newjob.id), seconds=intervals, start_date=starttime, end_date=endtime)
                    else:
                        cronplan = crontime.split(' ')
                        cminute = cronplan[0]
                        chour = cronplan[1]
                        cday = cronplan[2]
                        cmonth = cronplan[3]
                        cdayofweek = cronplan[4]
                        scheduler.add_job(getattr(JobTypeList, jtype.Shlrmethod), jobtrigger, args=jargslist, id=str(newjob.id), day_of_week=cdayofweek, month=cmonth, day=cday, hour=chour, minute=cminute, start_date=starttime, end_date=endtime)
                except Exception as e:
                    msg = e
                    return render(request, 'public/fail.html', {'msg': msg})
                return redirect('/myscheduler/schedulerjoblist')
        else:
            errors = sJob_form.errors
            return render(request, 'myscheduler/schedulerjob_add.html', {'obj': sJob_form,  'schedulertype': schedulertype, 'error': errors})
    return render(request, 'myscheduler/schedulerjob_add.html', {"obj": obj, 'schedulertype': schedulertype})


def GetJobarg(jtype, jargs, user):
    jarglist = jtype.Argslist
    if jargs and jarglist:
        largs = jarglist.split(',')
        rargs = jargs.split(',')
        if len(largs) != len(rargs):
            return None
        for i in range(len(largs)):
            rargs[i] = rargs[i].strip()
            if largs[i].strip() == 'extra_vars':
                rargs[i] = ast.literal_eval(rargs[i]) if rargs[i] else {}
        jlist = rargs
    elif not jargs and not jarglist:
        jlist = []
    else:
        return None
    jlist.insert(0, user)
    print(jlist)
    return jlist


def SchedulerJobDel(request):
    id = request.GET.get('id')
    sjob = scheduler.get_job(id)
    if sjob:
        scheduler.remove_job(id)
    SchedulerJob.objects.filter(id=id).delete()
    return redirect('/myscheduler/schedulerjoblist')


def SchedulerJobPause(request):
    if request.method == "GET":
        jobid = request.GET.get('jobid')
        print(jobid)
        sjob = scheduler.get_job(jobid)
        msg = "Pause Fail"
        if sjob:
            scheduler.pause_job(jobid)
            SchedulerJob.objects.filter(id=jobid).update(Jobstatus=1)
            msg = "Pause Success"
        return JsonResponse(msg, safe=False)


def SchedulerJobResume(request):
    jobid = request.GET.get('jobid')
    sjob = scheduler.get_job(jobid)
    msg = "Resume Fail"
    if sjob:
        scheduler.resume_job(jobid)
        SchedulerJob.objects.filter(id=jobid).update(Jobstatus=0)
        msg = "Resume Success"
    return JsonResponse(msg, safe=False)


scheduler.start()
